from datetime import datetime, timedelta

import jwt
from fastapi import Depends
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jwt import PyJWTError
from passlib.context import CryptContext

from app.model.mysql import User
from app.settings.config import SECRET_KEY, ALGORITHM
from app.validator.app.schemas import TokenData
from app.core.BaseResponse import UnicornException

pwd_context = CryptContext(schemes=['bcrypt'])
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/token")


def verify_password(plain_password, hashed_password):
    """用于验证收到的密码是否与存储的哈希匹配"""
    return pwd_context.verify(plain_password, hashed_password)


def get_password_hash(password):
    return pwd_context.hash(password)


# async def authenticate_user(username: str, password: str):
#     user = await User.filter(username=username).first()
#
#     if not user or not verify_password(password, user.password):
#         raise HTTPException(
#             status_code=status.HTTP_401_UNAUTHORIZED,
#             detail="Incorrect username or password",
#             headers={"WWW-Authenticate": "Bearer"},
#         )
#
#     return user  # <class '__main__.UserInDB'>


def create_access_token(*, data: dict, expires_delta: timedelta = None):
    """创建访问令牌"""
    to_encode = data.copy()

    expire = datetime.utcnow() + expires_delta  # expire 令牌到期时间
    to_encode.update({"exp": expire})

    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt


async def get_current_user(token: str = Depends(oauth2_scheme)):
    """获取当前用户"""
    credentials_exception = UnicornException(
        code=-1,
        errmsg="凭证失效",
    )

    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        mobile: str = payload.get("sub")
        if mobile is None:
            raise credentials_exception
        token_data = TokenData(mobile=mobile)
    except PyJWTError:
        raise credentials_exception
    user = await User.filter(mobile=token_data.mobile).first()
    if user is None:
        raise credentials_exception

    return user

# async def get_current_active_user(current_user: UserValidator = Depends(get_current_user)):
#     if current_user.disabled:
#         raise HTTPException(status_code=400, detail="Inactive user")
#     return current_use
